// testing of the dominion.c shuffle() function

#include <stdio.h>
#include <stdlib.h>
#include "dominion.h"
#include "rngs.h"

//prints the results of the testing
void print_results(int a, int b){
	double results = ((double)a) / b;
	printf("---------------------\n");
	printf("shuffle() -- %.f%% of test cases passed (%d/%d)\n", (results*100), a, b);
}

//sets all the values in the game struct to 0
void init_gamestate(struct gameState *g){
	int i;
	for(i = 0; i < sizeof(struct gameState); i++){
		((char *)g)[i] = 0;
	}
}

int main(int argc, char **argv) {
	int i, j, k, temp, temp2;
	int player, deckCount, sum;
	double shuffle_quality;
	int shuffle_dist, total_shuffles;
	int good_test, bad_test, status;
	int randomSeed, test_count;
	int deckTracker[MAX_DECK+1];

	struct gameState g;
	
	if(argc != 3){
		printf("Usage: unittest2 [seed] [number of tests]\n");
		return(0);
	}
	//initialize vars
	randomSeed = atoi(argv[1]);
	test_count = atoi(argv[2]);
	shuffle_quality = shuffle_dist = total_shuffles = 0;
	good_test = bad_test = 0;
	
	// set up random number
	SelectStream(1);
	PutSeed((long)randomSeed);
	
	for(i = 0; i < test_count; i++){
		//create random inputs
		init_gamestate(&g); //init game state
		player = (int)(Random()*(MAX_PLAYERS-1))+1; //random player
		deckCount = (int)(Random()*(MAX_DECK-1))+1; //random deck size > 0
		g.deckCount[player] = deckCount;
		//create the deck
		for(j = 0; j < deckCount; j++){
			g.deck[player][j] = j+1;
		}
		
		//shuffle the deck
		shuffle(player, &g);
		
		//make sure the deck still has the same cards
		sum = status = 0;
		for(j = 0; j < MAX_DECK; j++){
			deckTracker[j] = -1; //init the deck tracker
		}
		for(j = 0; j < deckCount; j++){
			//make sure current card is in range
			if(g.deck[player][j] < 0 || g.deck[player][j] > MAX_DECK){
				status = -1;
				printf("deck is out of range\n");
				continue;
			}
			//mark the card in the deck tracker
			deckTracker[g.deck[player][j]] = 1;
		}
		//review the deck tracker and make sure we got all our cards
		for(j = 0; j < deckCount; j++){
			if(deckTracker[j+1] != 1){
				printf("deck missing a card\n");
				status = -1;
			}
		}
		if(status == -1){
			printf("Error: our deck doesn't have the same cards in it!\n");
			bad_test++;
			continue;
		}
		
		//see how shuffled the deck is
		sum = temp2 = 0;
		for(j = 0; j < deckCount; j++){
			temp = g.deck[player][j] - (j+1);
			if(temp < 0) temp *= -1;
			sum += temp;
			if(temp!=0) temp2++; //track whether or not the card moved
		}
		//save the number of cards moved in this shuffle
		shuffle_quality = shuffle_quality + ((temp2*1.0)/deckCount);
		//calculate the average distance for the shuffled cards
		shuffle_dist = (sum/deckCount);
		good_test++;
		total_shuffles++;
	}

	print_results(good_test, test_count);
	printf("On average, %.f%% of cards moved on each shuffle\n", 100*((double)(shuffle_quality)/total_shuffles));
	//printf("Average distance each card moved each correct shuffle = %d\n", shuffle_dist / total_shuffles);

	return 0;
}
